# -*- mode: python; coding: utf-8; -*-
##--------------------------------------------------------------------------##
##
## Copyright (C) 1998-2003 Markus Oberhumer <markus@oberhumer.com>
## Copyright (C) 2003 Mt. Hood Playing Card Co.
## Copyright (C) 2005-2010 Skomoroh <skomoroh@users.sourceforge.net>
## Copyright (C) 2010-2013 Jeremy Austin-Bardo <tjaustinbardo@gmail.com>
##
## This program is free software: you can redistribute it and/or modify
## it under the terms of the GNU General Public License as published by
## the Free Software Foundation, either version 3 of the License.
##
## This program is distributed in the hope that it will be useful,
## but WITHOUT ANY WARRANTY; without even the implied warranty of
## MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
## GNU General Public License for more details.
##
## You should have received a copy of the GNU General Public License
## along with this program.  If not, see <http://www.gnu.org/licenses/>.
##
##--------------------------------------------------------------------------##
"""
"""
from .. import formlib as layout

LEFT, RIGHT = layout.LEFT, layout.RIGHT


class FortyThievesLayout(layout.Layout):
    """
    static block:
      - foundations [N]. horz SUITS. max 10 cols.
      - reserves [S foundations]. `_offset` if `holdcards`. `ncards` if
        `reserve_texts`.
      - rows [S reserves] `_offset` if `playcards`. `ncols` wide.

    dynamic block: align [LEFT | RIGHT].
      - talon [SW | SE].
      - waste [E | W] talon. `_offset` if `wastecards`.

    :CVariables:
        _offset: func
          .. dict('ycards': [play|hold]cards)

          Margin and offset is below piles.

        _halign: func
          .. (max_rows - piles) * self.HXS

          Pile group alignment.
    """
    _offset = lambda self, cards: {'ycards': cards}
    _halign = lambda self, max_rows, piles: (max_rows - piles) * self.HXS

    def create(self, rows, ncols=None, playcards=12, bases=None,
               reserves=0, holdcards=0, reserve_texts=False,
               texts=True, align=LEFT, wastecards=0, **kw):
        """
        create(rows[, ncols=rows, playcards=16, bases=suits * decks,
               reserves=0, holdcards=0, reserve_texts=False,
               texts=True, align=RIGHT]) -> None

        :Parameters:
          rows : int
            Num of `s.rows` to include.

          ncols : int
            Num of horz piles before starting new row. Default `ROWS`.

          playcards : int
            Num of possible cards as margin on each pile on `s.rows`. A value
            of 0 sets no offset and a value greater sets an offset. Default
            `16`.

          bases : tuple | list
            Value of each `suit` capabilty on `s.foundations`. Len is num of
            piles to include. Default `SUITS * DECKS`.

          reserves : int
            Num of `s.reserves` piles to include. Default `0`.

          holdcards : int
            Num of possible cards as margin on each pile on `s.reserves`. A
            value of 0 sets no offset and a value greater sets an offset.
            Default `0`.

          reserve_texts : bool
            Whether to include num cards text label for `s.reserves`. Default
            `False`.

          texts : bool
            Whether to include num cards text label for `s.talon` and possible
            `s.waste`. Default `True`.

          align : LEFT | RIGHT
            Dynamic placement of `s.talon`, possible `s.waste`, and possible
            `s.reserves`. `s.foundations` placement is opposite side. Default
            `RIGHT`

          wastecards : int
            Num of possible cards as margin on each pile on `s.waste`. A
            value of 0 sets no offset and a value greater sets an offset.
            Default `0`.
        """
        l, s = self, self.s
        ncols = ncols or rows
        # set foundation base caps
        bases = bases if type(bases) in (list, tuple) else l.SUITS
        f_cols = min(10, (len(bases) / l.NDECKS) * min(2, l.NDECKS))
        # set max piles for centering groups
        max_cols = max(ncols, reserves, f_cols)
        row_align = lambda piles: l._halign(max_cols, piles)
        # allow sub class usage
        ix = max(l.size.width, l.XM)
        l._set_horz_foundations(x=ix + row_align(f_cols), y=l.YM,
                                ncols=f_cols, bases=bases)
        # adjust for reserve texts
        dy = l.TEXT_HEIGHT if reserves and reserve_texts else 0
        l._set_horz_reserves(x=ix + row_align(reserves), y=l.size.height + dy,
                            reserves=reserves, reserve_texts=reserve_texts,
                            anchor='n', **l._offset(holdcards))
        l._set_rows(x=ix + row_align(ncols), y=l.size.height, rows=rows,
                    ncols=ncols, **l._offset(playcards))
        # adjust for talon
        dx = ix if align == LEFT else l.size.width - l.XS
        # adjust for talon texts
        dy += l.TEXT_HEIGHT if texts else 0
        l._set_horz_talon(x=dx, y=l.size.height + dy, texts=texts,
                          align=align, anchor='n',
                          wastecards=wastecards)
        anchor = 'w' if align== RIGHT else'e'
        s['talon'].set_rounds(anchor='nnn'
                                  if l._has_waste and wastecards else anchor,
                           dx=l.XS * align
                              if l._has_waste and not wastecards else 0)


class PrimroseLayout(layout.Layout):
    """
    static block:
      - reserves [N]. `_offset` if `holdcards`. `ncards` if
        `reserve_texts`.
      - foundations [S reserves]. horz SUITS. max 10 cols.
      - rows [S foundations] `_offset` if `playcards`. `ncols` wide.

    dynamic block: align [LEFT | RIGHT].
      - talon [SW | SE].
      - waste [E | W] talon. `_offset` if `wastecards`.

    :CVariables:
        _offset: func
          .. dict('ycards': [play|hold]cards)

          Margin and offset is below piles.

        _halign: func
          .. (max_rows - piles) * self.HXS

          Pile group alignment.
    """
    _offset = lambda self, cards: {'ycards': cards}
    _halign = lambda self, max_rows, piles: (max_rows - piles) * self.HXS

    def create(self, rows, ncols=None, playcards=16, bases=None,
               reserves=0, holdcards=0, reserve_texts=False,
               texts=True, align=LEFT, wastecards=0, **kw):
        """
        create(rows[, ncols=rows, playcards=16, bases=suits * decks,
               reserves=0, holdcards=0, reserve_texts=False,
               texts=True, align=RIGHT]) -> None

        :Parameters:
          rows : int
            Num of `s.rows` to include.

          ncols : int
            Num of horz piles before starting new row. Default `ROWS`.

          playcards : int
            Num of possible cards as margin on each pile on `s.rows`. A value
            of 0 sets no offset and a value greater sets an offset. Default
            `16`.

          bases : tuple | list
            Value of each `suit` capabilty on `s.foundations`. Len is num of
            piles to include. Default `SUITS * DECKS`.

          reserves : int
            Num of `s.reserves` piles to include. Default `0`.

          holdcards : int
            Num of possible cards as margin on each pile on `s.reserves`. A
            value of 0 sets no offset and a value greater sets an offset.
            Default `0`.

          reserve_texts : bool
            Whether to include num cards text label for `s.reserves`. Default
            `False`.

          texts : bool
            Whether to include num cards text label for `s.talon` and possible
            `s.waste`. Default `True`.

          align : LEFT | RIGHT
            Dynamic placement of `s.talon`, possible `s.waste`, and possible
            `s.reserves`. `s.foundations` placement is opposite side. Default
            `RIGHT`

          wastecards : int
            Num of possible cards as margin on each pile on `s.waste`. A
            value of 0 sets no offset and a value greater sets an offset.
            Default `0`.
    """
        l, s = self, self.s
        ncols = ncols or rows
        # set foundation base caps
        bases = bases if type(bases) in (list, tuple) else l.SUITS
        f_cols = min(10, (len(bases) / l.NDECKS) * min(2, l.NDECKS))
        # set max piles for centering groups
        max_cols = max(ncols, reserves, f_cols)
        row_align = lambda piles: l._halign(max_cols, piles)
        # allow sub class usage
        ix = max(l.size.width, l.XM)
        l._set_horz_reserves(x=ix + row_align(reserves), y=l.YM,
                            reserves=reserves, reserve_texts=reserve_texts,
                            anchor='n', **l._offset(holdcards))
        # adjust for reserve texts
        dy = l.TEXT_HEIGHT if reserves and reserve_texts else 0
        l._set_horz_foundations(x=ix + row_align(f_cols),
                                y=l.size.height + dy, ncols=f_cols,
                                bases=bases)
        l._set_rows(x=ix + row_align(ncols), y=l.size.height, rows=rows,
                    ncols=ncols, **l._offset(playcards))
        # adjust for talon
        dx = ix if align == LEFT else l.size.width - l.XS
        # adjust for talon texts
        dy += l.TEXT_HEIGHT if texts else 0
        l._set_horz_talon(x=dx, y=l.size.height + dy, texts=texts,
                          align=align, anchor='n',
                          wastecards=wastecards)
        anchor = 'w' if align== RIGHT else'e'
        s['talon'].set_rounds(anchor='nnn'
                                  if l._has_waste and wastecards else anchor,
                           dx=l.XS * align
                              if l._has_waste and not wastecards else 0)



class OctaveLayout(FortyThievesLayout):
    """
    - top: (reserves), foundations over many cols. Default 2 suit sets or 10
      suits.
    - below: rows
    - bottom: talon, waste, xwastes
    """

    def defaultAll(self):
        """
        defaultAll() -> None

        Set default for texts, groups, and regions.
        """
        game = self.game
        xwastes = self.s['xwastes']
        if game.s['xwastes'] and xwastes:
            if xwastes.ncards:
                self.set_ncards_text(game.s.xwastes, **xwastes.ncards)
        super(OctaveLayout, self).defaultAll(self)

    def create(self, xwastes, waste_align, xwastestext=False, **kw):
        super(OctaveLayout, self).create(**kw)
        align = kw.get('align', LEFT)
        l, s, = self, self.s
        assert l._has_waste
        x, y = s['waste'].x, s['waste'].y
        waste = s['wastes'][-1]
        if align == LEFT:
            if waste_align == RIGHT:
                waste = l._create_stack(l.size.width - l.XS, y)
            else:
                x += l.XS
        else:
            if waste_align == LEFT:
                waste = l._create_stack(l.XM, y)
            else:
                x -= min(l.XM, l.XS * xwastes)
        waste._set_offset(0, 0)
        s['wastes'] = []
        for x in l.row_iter(x, xwastes):
            s['wastes'].append(self._create_stack(x, y))
            if xwastestext:
                s['wastes'][-1].set_ncards(anchor='n')
        s['wastes'].append(waste)  # waste is always last